import java.io.File;
import java.util.HashSet;
import java.util.Set;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

public class ParsingPlanningGraph {

	private Document servicesDoc, taxonomyDoc, challengeDoc;
	private NodeList taxInstances, taxConcepts, servicesNList;

	// File paths for all needed documents. (Modify this according to your project setup)

	//private final String SERVICES_PATH = "Services.wsdl";
	//private final String TAXONOMY_PATH = "Taxonomy.xml" ;
	//private final String CHALLENGE_PATH = "Challenge.wsdl";

//  
	private final String SERVICES_PATH = "C:/WSC2009_Testsets/Testset01/Services.wsdl";
	private final String TAXONOMY_PATH = "C:/WSC2009_Testsets/Testset01/taxonomy.xml";
	private final String CHALLENGE_PATH = "C:/WSC2009_Testsets/Testset01/Challenge.wsdl";

	public ParsingPlanningGraph() {
		try {
			// Initialize document files.
			servicesDoc  = createDoc(SERVICES_PATH);
			taxonomyDoc  = createDoc(TAXONOMY_PATH);
			challengeDoc = createDoc(CHALLENGE_PATH);
	
			// Initialize node lists needed for later parsing.
			taxInstances  = taxonomyDoc.getElementsByTagName("instance");
			taxConcepts   = taxonomyDoc.getElementsByTagName("concept");
			servicesNList = servicesDoc.getElementsByTagName("service");
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public Document createDoc(String filepath) throws Exception {
		File fXmlFile = new File(filepath);
		DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
		DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
		Document doc = dBuilder.parse(fXmlFile);
		return doc;
	}

	public Thing parsingThing(String instanceName) throws Exception {
		String conceptName = "";
		for (int i = 0; i < taxInstances.getLength(); i++) {
			Node node = taxInstances.item(i);
			if (node.getNodeType() == Node.ELEMENT_NODE) {
				Element eElement = (Element) node;
				String name = eElement.getAttribute("name");
				if (name.equals(instanceName)) {
					Element parent = (Element) node.getParentNode();
					conceptName = parent.getAttribute("name");
					break;
				}
			}
		}
		// create its concept
		Concept concept = new Concept(conceptName);

		// create thing
		Thing thing = new Thing(instanceName, concept);
		return thing;
	}

	public Set<Concept> parsingParentConcepts(String conceptName) throws Exception {
		String parentConceptName = "";
		String root = taxonomyDoc.getDocumentElement().getNodeName();
		Set<Concept> parentConcepts = new HashSet<Concept>();

		for (int i = 0; i < taxConcepts.getLength(); i++) {
			Node node = taxConcepts.item(i);
			if (node.getNodeType() == Node.ELEMENT_NODE) {
				Element eElement = (Element) node;
				String name = eElement.getAttribute("name");
				if (name.equals(conceptName)) {
					Node parentNode = node.getParentNode();
					while (!parentNode.getNodeName().equals(root)) {
						Element parent = (Element) parentNode;
						parentConceptName = parent.getAttribute("name");
						Concept concept = new Concept(parentConceptName);
						parentConcepts.add(concept);
						parentNode = parentNode.getParentNode();
					}
					return parentConcepts;
				}
			}
		}
		return null;
	}

	/*
	 * Service parsing function. Returns a HashSet of Services.
	 */

	public Set<Service> parseServices1() throws Exception {
		Service service = null;
		Set<Service> serviceList = new HashSet<Service>();
		
		NodeList nList = servicesDoc.getElementsByTagName("mece:semMessageExt");
		String serviceName = "";
		String str = "";
		for (int i = 0; i < nList.getLength(); i++) {			
			Node nNode = nList.item(i);
			if (nNode.getNodeType() == Node.ELEMENT_NODE) {
				Element eElement = (Element) nNode;
				
				str = eElement.getAttribute("id");
				if (!str.replace("RequestMessage", "").equals(serviceName) && !str.replace("ResponseMessage", "").equals(serviceName)) {
					serviceName = str.replace("RequestMessage", ""); 
					service = new Service(serviceName);
					NodeList inputNodes = nNode.getChildNodes();
					for (int j = 0; j < inputNodes.getLength(); j++) {
						Node instanceNode = inputNodes.item(j);
						if (instanceNode.getNodeType() == Node.ELEMENT_NODE) {
						Element eInstance = (Element) instanceNode;
						String instance = eInstance.getTextContent().replace(
								"http://www.ws-challenge.org/wsc08.owl#", "");
						Thing thing = parsingThing(instance.trim());
						Concept con = thing.getConcept();
						service.addInputConcept(con);
						}
					}
					serviceList.add(service);
				}
				else {
					NodeList outputNodes = nNode.getChildNodes();
					for (int j = 0; j < outputNodes.getLength(); j++) {
						Node instanceNode = outputNodes.item(j)/*.getChildNodes().item(0)*/;
						if (instanceNode.getNodeType() == Node.ELEMENT_NODE) {
						Element eInstance = (Element) instanceNode;
						String instance = eInstance.getTextContent().replace(
								"http://www.ws-challenge.org/wsc08.owl#", "");
						Thing thing = parsingThing(instance.trim());
						Concept con = thing.getConcept();
						service.addOutputConcept(con);
						Set<Concept> pc = parsingParentConcepts(con.getName());
						// ...and add its parent concepts to service.
						for (Concept c : pc)
							service.addOutputConcept(c);
						}
					}
				}					
			}
		}
				

//		NodeList nList = servicesDoc.getElementsByTagName("mece:semExt");
//		String serviceName = "";
//		for (int i = 0; i < nList.getLength(); i++) {
//
//			Node nNode = nList.item(i);
//			if (nNode.getNodeType() == Node.ELEMENT_NODE) {
//				Element eElement = (Element) nNode;
//				Element taskInfo = (Element) eElement.getParentNode();
//				String str;
//				str = taskInfo.getAttribute("id");
//
//				if (!serviceName.equals(str.substring(0, 12))) {
//					serviceName = str.substring(0, 12);
//					service = new Service(serviceName);
//				}
//				if (str.contains("Request")) {
//					String instance = eElement.getTextContent().replace(
//							"http://www.ws-challenge.org/wsc08.owl#", "");
//				
//					Thing thing = parsingThing(instance.trim());
//					Concept con = thing.getConcept();
//					service.addInputConcept(con);
//					/*Set<Concept> pc = parsingParentConcepts(con.getName());
//					// ...and add its parent concepts to service.
//					for (Concept c : pc)
//						service.addInputConcept(c);*/
//				} else {
//					String instance = eElement.getTextContent().replace(
//							"http://www.ws-challenge.org/wsc08.owl#", "");
//					Thing thing = parsingThing(instance.trim());
//					Concept con = thing.getConcept();
//					service.addOutputConcept(con);
//					Set<Concept> pc = parsingParentConcepts(con.getName());
//					// ...and add its parent concepts to service.
//					for (Concept c : pc)
//						service.addOutputConcept(c);
//				}
//				serviceList.add(service);
//			}
//		}
		System.out.println(serviceList.size());
		return serviceList;
	}
	public Set<Service> parseServices() throws Exception {
	// Create empty Set to fill.
	HashSet<Service> serviceList = new HashSet<Service>();
	String serviceId = "";
	
	//System.out.println("Number of services: " + servicesNList.getLength());

	//System.out.println("Parsing services...");
	for (int i = 0; i < servicesNList.getLength(); i++) {
		// Current node (service).
		Node currentNode = servicesNList.item(i);
		// Create Service object.
		serviceId = currentNode.getAttributes().getNamedItem("name").getNodeValue();

		Service service = new Service(serviceId);

		// Get Input and Output lists.
		NodeList inputList = currentNode.getChildNodes().item(0).getChildNodes();
		NodeList outputList = currentNode.getChildNodes().item(1).getChildNodes();

		// March through both lists to get Concepts.
		// ------------------INPUT CONCEPTS------------------
		for (int j = 0; j < inputList.getLength(); j++) {
			// Get instance name.
			String instanceName = inputList.item(j).getAttributes().getNamedItem("name").getNodeValue();
			// Create Thing object...
			Thing thing = new Thing();
			thing = parsingThing(instanceName);
			// ...to get its Concept.
			Concept concept = thing.getConcept();
			// Get its parent concepts.
			Set<Concept> pc = parsingParentConcepts(concept.getName());
			// Add input concept to service...
			service.addInputConcept(concept);
			// ...and add its parent concepts to service.
			for (Concept c : pc)
				service.addInputConcept(c);
		}
		// -----------------OUTPUT CONCEPTS------------------
		for (int j = 0; j < outputList.getLength(); j++) {
			// Get instance name.
			String instanceName = outputList.item(j).getAttributes().getNamedItem("name").getNodeValue();
			// Create Thing object...
			Thing thing = new Thing();
			thing = parsingThing(instanceName);
			// ...to get its Concept.
			Concept concept = thing.getConcept();
			// Add output concept to service.
			service.addOutputConcept(concept);
			Set<Concept> pc = parsingParentConcepts(concept.getName());
			// ...and add its parent concepts to service.
			for (Concept c : pc)
				service.addOutputConcept(c);
			
		}

		//System.out.println("Displaying service values...");
		//System.out.println(service.toString());
		serviceList.add(service);
	}
	return serviceList;
} // End function.
	// parsingChallenge() - will initialize the Planning Graph.
	public PlanningGraph parsingChallenge() throws Exception {

		PlanningGraph pg = new PlanningGraph();
		// Document doc = createDoc(CHALLENGE_PATH);
		NodeList nList = challengeDoc.getElementsByTagName("mece:semExt");
		// System.out.println(nList.getLength());
		for (int i = 0; i < nList.getLength(); i++) {

			Node nNode = nList.item(i);
			if (nNode.getNodeType() == Node.ELEMENT_NODE) {
				Element eElement = (Element) nNode;
				Element taskInfo = (Element) eElement.getParentNode();
				if (taskInfo.getAttribute("id").contains("Request")) {
					String instance = eElement.getTextContent().replace("http://www.ws-challenge.org/wsc08.owl#", "");
					// System.out.println("request"+instance.trim());
					Thing thing = parsingThing(instance.trim());

					//System.out.println(instance.trim());
					pg.givenSet.add(thing.getConcept());
					Set<Concept> pc = parsingParentConcepts(thing.getConcept().getName());
					// Add input concept to service...
					//service.addInputConcept(concept);
					// ...and add its parent concepts to service.
					for (Concept c : pc)
						pg.givenSet.add(c);

					//Set<Concept> pc = parsingParentConcepts(thing.getConcept().getName());
					// Add input concept to service...
					//service.addInputConcept(concept);
					// ...and add its parent concepts to service.
					//for (Concept c : pc)
						//pg.addGivenConcept(c);
				} else {

					String instance = eElement.getTextContent().replace("http://www.ws-challenge.org/wsc08.owl#", "");
					// System.out.println("respons"+instance.trim());
					Thing thing = parsingThing(instance.trim());
					pg.goalSet.add(thing.getConcept());
				}
			}
		}
		
		return pg;
	}

	
}
